﻿using System;
using System.Collections.ObjectModel;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading;
using static FCTIP20.ViewModel.MainWindowModel;

namespace FCTIP20.Procdure
{
    public class FactoryArray
    {
        public string ModuleType { get; set; }
        public byte slotId { get; set; }
        public byte bpCommAddr { get; set; }
        public uint id { get; set; }
        public string name { get; set; }
        public string HW { get; set; }
        public string sn { get; set; }
        public string mac { get; set; }

    }
    public class FactoryApp
    {
        public ObservableCollection<FactoryArray> ReslutArray { get; set; }
        // 枚举类型定义（需与C++保持一致）
        public enum FactoryCommunicationApi
        {
            FACTORY_SERIAL_API = 0,
            FACTORY_TCP_CLIENT_API,
            FACTORY_UDP_API,
            FACTORY_EOE_TCP_CLIENT,
            FACTORY_EOE_UDP_API
        }

        public enum FactoryModuleType
        {
            FACTORY_COUPLER_MODULE,
            FACTORY_FORWARD_MODULE,
            FACTORY_SLAVE_MODULE
        }

        public enum FactoryCbType
        {
            FACTORY_INIT_CB_TYPE = 0,        // 初始化操作回调类型
            FACTORY_DEINIT_CB_TYPE,      // 反初始化操作回调类型
            FACTORY_SCAN_CB_TYPE,        // 模块扫描回调类型
            FACTORY_WRITE_CB_TYPE,       // 模块写入回调类型
        }

        // 串口参数结构体
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct SerialApiParam
        {
            public byte port;
            public uint baud;
        }

        // 通讯参数结构体
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct FactoryCommunicationParam
        {
            public SerialApiParam serial;
            public IntPtr tcpClient; // 这里只用串口，其他可忽略
            public IntPtr udpClient;
        }
        // 模块返回数据结构
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct FactoryModuleScanData
        {
            public FactoryModuleType type;
            public byte slotId;
            public byte bpCommAddr;
            public uint id;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            public byte[] hwVersion; //模块硬件版本
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            public byte[] name; // 模块名称
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            public byte[] sn; // 模块序列号
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
            public byte[] mac; // 模块 MAC 地址
        }
        // 回调委托
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        public delegate void OnfactoryNotify(
            byte commAddr,
            int cbType,
            int status,
            int api,
            IntPtr data,
            uint datalen);

        // DLL导入
        [DllImport("FactoryApp.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int jq_factory_init(
            FactoryCommunicationApi api,
            ref FactoryCommunicationParam param,
            OnfactoryNotify cb);

        [DllImport("FactoryApp.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int jq_factory_deinit(FactoryCommunicationApi api);

        [DllImport("FactoryApp.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int jq_factory_module_scan(FactoryCommunicationApi api);
       
        private static ManualResetEvent notifyEvent = new ManualResetEvent(false);
        
        // 回调实现
        public void NotifyCallback(byte commAddr, int cbType, int status, int api, IntPtr data, uint datalen)
        {
            
            //Console.WriteLine($"[回调] commAddr={commAddr}, cbType={cbType}, status={status}, api={api} ,data={data} ,datalen={datalen}");
            // 可根据cbType和status进一步处理
            if ((FactoryCbType)cbType == FactoryCbType.FACTORY_SCAN_CB_TYPE)
            {
                int factoryModuleSize = Marshal.SizeOf(typeof(FactoryModuleScanData));
                int numModules = (int)(datalen / factoryModuleSize);
                for (int i = 0; i < numModules; i++)
                {
                    IntPtr modulePtr = IntPtr.Add(data, i * factoryModuleSize);
                    FactoryModuleScanData module = Marshal.PtrToStructure<FactoryModuleScanData>(modulePtr);
                    string hwVersion = System.Text.Encoding.UTF8.GetString(module.hwVersion).TrimEnd('\0');
                    string name = System.Text.Encoding.UTF8.GetString(module.name).TrimEnd('\0');
                    string sn = System.Text.Encoding.UTF8.GetString(module.sn).TrimEnd('\0');
                    string mac = BitConverter.ToString(module.mac).Replace("-", ":");
                    //Console.WriteLine($"模块{i + 1}:SN = {sn},MAC = {mac},SLotId = {module.slotId},BPCommAddr = {module.bpCommAddr},ID = {module.id},ModuleType = {module.type}");
                    ReslutArray.Add(new FactoryArray {slotId = module.slotId ,ModuleType = module.type.ToString(), id = module.id,bpCommAddr = module.bpCommAddr,sn = sn, mac = mac, name = name, HW = hwVersion });
                }
            }
            notifyEvent.Set(); // 唤醒等待线程
        }
        public ObservableCollection<FactoryArray> Main(byte port)
        {
            ReslutArray = new ObservableCollection<FactoryArray>();
            // 配置串口参数
            var serialParam = new SerialApiParam { port = port, baud = 921600 };
            var commParam = new FactoryCommunicationParam
            {
                serial = serialParam,
                tcpClient = IntPtr.Zero,
                udpClient = IntPtr.Zero
            };

            // 注册回调c
            OnfactoryNotify cb = NotifyCallback;

            // 初始化
            notifyEvent.Reset();
            int ret = jq_factory_init(FactoryCommunicationApi.FACTORY_SERIAL_API, ref commParam, cb);

            // 等待回调
            notifyEvent.WaitOne();
            notifyEvent.Reset();

            // 模块扫描
            ret = jq_factory_module_scan(FactoryCommunicationApi.FACTORY_SERIAL_API);

            // 等待回调
            notifyEvent.WaitOne();
            notifyEvent.Reset();
            // 反初始化
            ret = jq_factory_deinit(FactoryCommunicationApi.FACTORY_SERIAL_API);

            return ReslutArray;

        }
    }
    
}
